// GitCode 代码树查看器 Content Script
(function() {
  'use strict';

  // 配置
  const CONFIG = {
    treeWidth: 280,
    toggleKey: 'Alt+T',
    storageKey: 'gitcode-tree-enabled',
    tokenKey: 'gitcode-tree-token',
    cachePrefix: 'gitcode-tree-cache-',
    cacheExpiry: 30 * 60 * 1000 // 30分钟缓存过期
  };
  
  // 从存储中获取token
  function getApiToken() {
    return new Promise((resolve) => {
      chrome.storage.local.get([CONFIG.tokenKey], (result) => {
        resolve(result[CONFIG.tokenKey] || '');
      });
    });
  }

  // 获取当前文件路径
  function getCurrentFilePath() {
    const path = window.location.pathname;
    // GitCode路径格式: /owner/repo/blob/branch/path
    const match = path.match(/\/blob\/[^\/]+\/(.+)/);
    return match ? match[1] : null;
  }

  let treeContainer = null;
  let isVisible = false;
  let currentRepo = null;
  let fileTree = null;
  let cache = {}; // 内存缓存
  let currentPath = ''; // 当前路径栈
  let pathStack = []; // 路径历史栈
  let isManualCollapse = false; // 标记是否是手动收起操作，用于阻止自动定位
  let manuallyCollapsedPaths = new Set(); // 记录用户手动收起的目录路径，避免自动重新展开

  // 初始化
  async function init() {
    // 检查是否在代码仓库页面
    if (!isRepoPage()) {
      return;
    }

    // 从存储中读取设置
    chrome.storage.local.get([CONFIG.storageKey], (result) => {
      isVisible = result[CONFIG.storageKey] !== false; // 默认启用
      if (isVisible) {
        createTreeViewer();
      }
    });

    // 监听存储变化
    chrome.storage.onChanged.addListener((changes) => {
      if (changes[CONFIG.storageKey]) {
        isVisible = changes[CONFIG.storageKey].newValue !== false;
        if (isVisible && !treeContainer) {
          createTreeViewer();
        } else if (!isVisible && treeContainer) {
          removeTreeViewer();
        }
      }
      if (changes[CONFIG.tokenKey] && treeContainer) {
        // Token更新时刷新文件树
        loadFileTree(currentPath || '');
      }
    });

    // 监听来自popup的消息
    chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
      if (request.action === 'refresh' && treeContainer) {
        loadFileTree(currentPath || '');
      }
    });

    // 键盘快捷键
    document.addEventListener('keydown', (e) => {
      if (e.altKey && e.key === 't') {
        e.preventDefault();
        toggleTreeViewer();
      }
    });
  }

  // 检查是否在代码仓库页面
  function isRepoPage() {
    const path = window.location.pathname;
    // GitCode仓库页面路径格式: /用户名/仓库名 或 /用户名/仓库名/tree/分支名
    return /^\/[^\/]+\/[^\/]+/.test(path);
  }

  // 获取当前仓库信息
  function getRepoInfo() {
    const path = window.location.pathname;
    const match = path.match(/^\/([^\/]+)\/([^\/]+)/);
    if (!match) return null;

    const [, owner, repo] = match;
    
    // 提取分支名和路径
    let branch = 'master';
    let currentPath = '';
    
    // GitCode路径格式: /owner/repo/tree/branch/path 或 /owner/repo/blob/branch/path
    const treeMatch = path.match(/\/tree\/([^\/]+)(?:\/(.*))?/);
    if (treeMatch) {
      branch = treeMatch[1];
      currentPath = treeMatch[2] || '';
    } else {
      const blobMatch = path.match(/\/blob\/([^\/]+)(?:\/(.*))?/);
      if (blobMatch) {
        branch = blobMatch[1];
        const blobPath = blobMatch[2] || '';
        // 从文件路径提取目录路径
        if (blobPath) {
          const pathParts = blobPath.split('/');
          pathParts.pop(); // 移除文件名
          currentPath = pathParts.join('/');
        }
      }
    }

    return {
      owner,
      repo,
      branch,
      currentPath: currentPath, // 当前目录路径
      path: path.replace(/\/(tree|blob)\/[^\/]+/, '') || `/${owner}/${repo}`
    };
  }

  // 创建代码树查看器
  function createTreeViewer() {
    if (treeContainer) return;

    currentRepo = getRepoInfo();
    if (!currentRepo) return;

    // 创建容器
    treeContainer = document.createElement('div');
    treeContainer.id = 'gitcode-tree-viewer';
    treeContainer.innerHTML = `
      <div class="gitcode-tree-header">
        <div class="gitcode-tree-title">
          <svg width="16" height="16" viewBox="0 0 16 16" fill="currentColor">
            <path d="M3.75 0a.75.75 0 0 0-.75.75v14.5c0 .414.336.75.75.75h8.5a.75.75 0 0 0 .75-.75V7.5H9.75a.75.75 0 0 1-.75-.75V4.5H3.75a.75.75 0 0 0-.75.75zm5.75.56v2.19h2.19L9.5.56zM2.5 1.5v13h9v-6h-3.5a.75.75 0 0 1-.75-.75v-3.5H2.5z"/>
          </svg>
          <span>代码树</span>
        </div>
        <div class="gitcode-tree-controls">
          <button class="gitcode-tree-back" title="返回上一级" data-action="back" style="display: none;">←</button>
          <button class="gitcode-tree-toggle" title="收起/展开" data-action="toggle-all">−</button>
          <button class="gitcode-tree-settings" title="设置Token" data-action="settings">⚙</button>
          <button class="gitcode-tree-close" title="关闭 (Alt+T)" data-action="close">×</button>
        </div>
      </div>
      <div class="gitcode-tree-token-panel" id="tokenPanel" style="display: none;">
        <div class="gitcode-tree-token-header">
          <span>设置 API Token</span>
          <button class="gitcode-tree-token-close" data-action="close-token">×</button>
        </div>
        <div class="gitcode-tree-token-body">
          <input type="password" id="tokenInputInline" placeholder="输入GitCode API Token" class="gitcode-tree-token-input">
          <div class="gitcode-tree-token-info">
            <p>• Token用于访问GitCode API获取代码树数据</p>
            <p>• 可在GitCode设置中生成Personal Access Token</p>
            <p>• Token会安全保存在本地，不会上传到任何服务器</p>
          </div>
          <button class="gitcode-tree-token-save" id="saveTokenInline">保存Token</button>
        </div>
      </div>
      <div class="gitcode-tree-search">
        <input type="text" placeholder="搜索文件..." class="gitcode-tree-search-input">
      </div>
      <div class="gitcode-tree-content">
        <div class="gitcode-tree-loading">加载中...</div>
      </div>
    `;

    document.body.appendChild(treeContainer);

    // 绑定事件
    bindEvents();
    
    // 初始化路径栈
    currentPath = '';
    pathStack = [];
    
    // 加载代码树（只加载根目录）
    loadFileTree('');
    
    // 如果当前在文件页面，自动展开路径并高亮（延迟更长时间确保DOM已渲染）
    const currentFilePath = getCurrentFilePath();
    if (currentFilePath) {
      setTimeout(() => {
        highlightCurrentFile();
      }, 800);
    }
  }

  // 绑定事件
  function bindEvents() {
    if (!treeContainer) return;

      // 关闭按钮
      treeContainer.querySelector('.gitcode-tree-close').addEventListener('click', () => {
        toggleTreeViewer();
      });

      // 返回上一级按钮
      treeContainer.querySelector('.gitcode-tree-back').addEventListener('click', () => {
        goBack();
      });

      // 设置按钮
      const settingsBtn = treeContainer.querySelector('.gitcode-tree-settings');
      if (settingsBtn) {
        settingsBtn.addEventListener('click', () => {
          toggleTokenPanel();
        });
      }

      // Token面板关闭按钮
      const tokenCloseBtn = treeContainer.querySelector('.gitcode-tree-token-close');
      if (tokenCloseBtn) {
        tokenCloseBtn.addEventListener('click', () => {
          toggleTokenPanel();
        });
      }

      // Token保存按钮
      const saveTokenBtn = treeContainer.querySelector('#saveTokenInline');
      if (saveTokenBtn) {
        saveTokenBtn.addEventListener('click', () => {
          saveTokenInline();
        });
      }

      // Token输入框回车保存
      const tokenInputInline = treeContainer.querySelector('#tokenInputInline');
      if (tokenInputInline) {
        tokenInputInline.addEventListener('keypress', (e) => {
          if (e.key === 'Enter') {
            saveTokenInline();
          }
        });
        
        // 加载已保存的token（显示为*号）
        chrome.storage.local.get([CONFIG.tokenKey], (result) => {
          if (result[CONFIG.tokenKey]) {
            tokenInputInline.value = result[CONFIG.tokenKey].replace(/./g, '*');
            tokenInputInline.dataset.hasValue = 'true';
          }
        });
        
        // 焦点时清空
        tokenInputInline.addEventListener('focus', () => {
          if (tokenInputInline.dataset.hasValue === 'true') {
            tokenInputInline.value = '';
            tokenInputInline.dataset.hasValue = 'false';
          }
        });
      }

      // 展开/收起所有
      treeContainer.querySelector('.gitcode-tree-toggle').addEventListener('click', (e) => {
        const btn = e.target;
        const isExpanded = btn.textContent === '−';
        toggleAllNodes(!isExpanded);
        btn.textContent = isExpanded ? '+' : '−';
      });

    // 搜索功能（暂时禁用，因为现在是懒加载模式）
    // const searchInput = treeContainer.querySelector('.gitcode-tree-search-input');
    // searchInput.addEventListener('input', (e) => {
    //   filterTree(e.target.value);
    // });

    // 拖拽调整宽度
    makeResizable();
  }


  // 加载文件树（只加载指定路径的一级目录，不递归）
  async function loadFileTree(path = '') {
    const contentDiv = treeContainer.querySelector('.gitcode-tree-content');
    contentDiv.innerHTML = '<div class="gitcode-tree-loading">加载中...</div>';

    // 等待页面完全加载（仅首次）
    if (path === '' && document.readyState !== 'complete') {
      await new Promise(resolve => {
        if (document.readyState === 'complete') {
          resolve();
        } else {
          window.addEventListener('load', resolve);
          setTimeout(resolve, 3000);
        }
      });
      await new Promise(resolve => setTimeout(resolve, 500));
    }

    try {
      // 只获取指定路径的一级内容（不递归）
      const contents = await fetchDirectoryContents(path);
      
      if (!contents || contents.length === 0) {
        console.warn('未找到任何文件');
        contentDiv.innerHTML = `
          <div class="gitcode-tree-error">
            <p>未找到文件列表</p>
            <p style="font-size: 11px; color: #586069; margin-top: 8px;">
              ${path ? `路径: ${path}` : '请确保在代码仓库页面使用此扩展'}
            </p>
            <button class="gitcode-tree-retry">重试</button>
          </div>
        `;
        contentDiv.querySelector('.gitcode-tree-retry').addEventListener('click', () => loadFileTree(path));
      } else {
        renderDirectoryContents(contents, path);
      }
    } catch (error) {
      console.error('加载文件树失败:', error);
      contentDiv.innerHTML = `
        <div class="gitcode-tree-error">
          <p>加载失败</p>
          <p style="font-size: 11px; color: #586069; margin-top: 8px;">${error.message}</p>
          <button class="gitcode-tree-retry">重试</button>
        </div>
      `;
      contentDiv.querySelector('.gitcode-tree-retry').addEventListener('click', () => loadFileTree(path));
    }
  }

  // 获取目录内容（带缓存）
  async function fetchDirectoryContents(path = '') {
    const cacheKey = `${currentRepo.owner}/${currentRepo.repo}/${currentRepo.branch}/${path}`;
    
    // 检查内存缓存
    if (cache[cacheKey] && Date.now() - cache[cacheKey].timestamp < CONFIG.cacheExpiry) {
      console.log(`从内存缓存加载: ${path || '根目录'}`);
      return cache[cacheKey].data;
    }
    
    // 检查 localStorage 缓存
    try {
      const cached = localStorage.getItem(CONFIG.cachePrefix + cacheKey);
      if (cached) {
        const cachedData = JSON.parse(cached);
        if (Date.now() - cachedData.timestamp < CONFIG.cacheExpiry) {
          console.log(`从 localStorage 缓存加载: ${path || '根目录'}`);
          cache[cacheKey] = cachedData;
          return cachedData.data;
        }
      }
    } catch (e) {
      console.log('读取缓存失败:', e);
    }

    // 从 API 获取
    console.log(`从 API 加载: ${path || '根目录'}`);
    const { owner, repo, branch } = currentRepo;
    const apiToken = await getApiToken();
    
    try {
      let contentsUrl = `https://gitcode.com/api/v5/repos/${owner}/${repo}/contents${path ? '/' + encodeURIComponent(path) : ''}?ref=${branch}`;
      const headers = {
        'Accept': 'application/json'
      };
      
      if (apiToken) {
        headers['Authorization'] = `Bearer ${apiToken}`;
        headers['PRIVATE-TOKEN'] = apiToken;
      }
      
      let contentsResponse = await fetch(contentsUrl, {
        method: 'GET',
        headers: headers,
        credentials: 'include'
      });
      
      if (!contentsResponse.ok) {
        contentsUrl = `https://api.gitcode.com/api/v5/repos/${owner}/${repo}/contents${path ? '/' + encodeURIComponent(path) : ''}?ref=${branch}`;
        contentsResponse = await fetch(contentsUrl, {
          method: 'GET',
          headers: headers
        });
      }
      
      if (contentsResponse.ok) {
        const contentType = contentsResponse.headers.get('content-type');
        if (contentType && contentType.includes('application/json')) {
          const text = await contentsResponse.text();
          const data = JSON.parse(text);
          
          if (Array.isArray(data)) {
            // 保存到缓存
            const cacheData = {
              data: data,
              timestamp: Date.now()
            };
            cache[cacheKey] = cacheData;
            try {
              localStorage.setItem(CONFIG.cachePrefix + cacheKey, JSON.stringify(cacheData));
            } catch (e) {
              console.log('保存缓存失败:', e);
            }
            
            return data;
          }
        }
      } else {
        console.log('API 请求失败，状态码:', contentsResponse.status);
        throw new Error(`API 请求失败: ${contentsResponse.status}`);
      }
    } catch (e) {
      console.log('API 获取失败:', e);
      throw e;
    }
    
    return [];
  }

  // 获取文件树（已废弃，保留用于兼容）
  async function fetchFileTree() {
    const { owner, repo, branch, currentPath } = currentRepo;
    
    // 方法1: 尝试从 GitCode API v5 获取
    try {
      // GitCode API v5 格式: /api/v5/repos/{owner}/{repo}/contents/{path}?ref={branch}
      // 或者使用 projects API: /api/v5/projects/{id}/repository/tree
      
      // 先尝试获取项目ID（通过项目信息接口）
      const apiToken = await getApiToken();
      let projectId = null;
      const headers = {
        'Accept': 'application/json'
      };
      
      if (apiToken) {
        headers['Authorization'] = `Bearer ${apiToken}`;
        headers['PRIVATE-TOKEN'] = apiToken;
      }
      
      try {
        // 尝试使用 gitcode.com 域名下的 API（可能避免 CORS 问题）
        const projectUrl = `https://gitcode.com/api/v5/repos/${owner}/${repo}`;
        const projectResponse = await fetch(projectUrl, {
          method: 'GET',
          headers: headers,
          credentials: 'include' // 包含 cookies
        });
        
        if (projectResponse.ok) {
          const projectData = await projectResponse.json();
          projectId = projectData.id;
          console.log('获取到项目ID:', projectId);
        } else {
          console.log('获取项目信息失败，状态码:', projectResponse.status);
        }
      } catch (e) {
        console.log('获取项目信息失败，尝试直接使用路径', e);
        // 如果 gitcode.com 失败，尝试 api.gitcode.com
        try {
          const projectUrl = `https://api.gitcode.com/api/v5/repos/${owner}/${repo}`;
          const projectResponse = await fetch(projectUrl, {
            method: 'GET',
            headers: headers
          });
          
          if (projectResponse.ok) {
            const projectData = await projectResponse.json();
            projectId = projectData.id;
            console.log('通过 api.gitcode.com 获取到项目ID:', projectId);
          }
        } catch (e2) {
          console.log('api.gitcode.com 也失败:', e2);
        }
      }

      // 方法1a: 使用 projects API 获取完整文件树（递归）
      if (projectId) {
        try {
          // 优先使用 gitcode.com 域名
          const treeUrl = `https://gitcode.com/api/v5/projects/${projectId}/repository/tree?ref=${branch}&recursive=true&per_page=1000`;
          let treeResponse = await fetch(treeUrl, {
            method: 'GET',
            headers: headers,
            credentials: 'include'
          });
          
          // 如果失败，尝试 api.gitcode.com
          if (!treeResponse.ok) {
            const treeUrl2 = `https://api.gitcode.com/api/v5/projects/${projectId}/repository/tree?ref=${branch}&recursive=true&per_page=1000`;
            treeResponse = await fetch(treeUrl2, {
              method: 'GET',
              headers: headers
            });
          }
          
          if (treeResponse.ok) {
            const contentType = treeResponse.headers.get('content-type');
            if (contentType && contentType.includes('application/json')) {
              const text = await treeResponse.text();
              try {
                const data = JSON.parse(text);
                if (Array.isArray(data)) {
                  console.log('API v5 获取成功（projects API），文件数量:', data.length);
                  return buildTreeFromAPI(data, currentPath);
                }
              } catch (parseError) {
                console.log('JSON解析失败:', parseError, '响应内容:', text.substring(0, 200));
              }
            }
          } else {
            console.log('Projects API 请求失败，状态码:', treeResponse.status);
            if (treeResponse.status === 401) {
              console.log('需要认证，API可能需要访问令牌');
            }
          }
        } catch (e) {
          console.log('Projects API 获取失败', e);
        }
      }

      // 方法1b: 使用 repos API 获取根目录内容（然后递归获取完整树）
      try {
        // 优先使用 gitcode.com 域名（可能避免 CORS）
        let contentsUrl = `https://gitcode.com/api/v5/repos/${owner}/${repo}/contents?ref=${branch}`;
        let contentsResponse = await fetch(contentsUrl, {
          method: 'GET',
          headers: headers,
          credentials: 'include'
        });
        
        // 如果失败，尝试 api.gitcode.com
        if (!contentsResponse.ok) {
          contentsUrl = `https://api.gitcode.com/api/v5/repos/${owner}/${repo}/contents?ref=${branch}`;
          contentsResponse = await fetch(contentsUrl, {
            method: 'GET',
            headers: headers
          });
        }
        
        if (contentsResponse.ok) {
          const contentType = contentsResponse.headers.get('content-type');
          if (contentType && contentType.includes('application/json')) {
            const text = await contentsResponse.text();
            try {
              const data = JSON.parse(text);
              if (Array.isArray(data)) {
                console.log('API v5 获取成功（contents API），根目录文件数量:', data.length);
                // 注意：不再递归获取，只返回一级目录内容（懒加载模式）
                // 递归逻辑已移除，现在使用懒加载模式，点击时才加载子目录
                return data;
              }
            } catch (parseError) {
              console.log('Contents API JSON解析失败:', parseError);
            }
          }
        } else {
          console.log('Contents API 请求失败，状态码:', contentsResponse.status);
          if (contentsResponse.status === 401) {
            console.log('需要认证，API可能需要访问令牌');
          }
        }
      } catch (e) {
        console.log('Contents API 获取失败', e);
      }

    } catch (e) {
      console.log('API v5 获取失败，尝试解析页面', e);
    }

    // 方法2: 解析页面DOM（主要方法）
    console.log('使用DOM解析方式获取文件树');
    return buildTreeFromDOM();
  }

  // 从API数据构建树（projects API - 递归获取）
  function buildTreeFromAPI(items, currentPath = '') {
    const tree = { name: 'root', type: 'tree', children: [] };
    const pathMap = {};

    items.forEach(item => {
      // GitCode API 返回的格式可能是 { path, type, mode } 或 { name, type, path }
      const itemPath = item.path || item.name;
      const itemType = item.type; // 'blob' 或 'tree'
      
      if (!itemPath) return;

      const parts = itemPath.split('/').filter(p => p);
      let current = tree;

      parts.forEach((part, index) => {
        const isFile = index === parts.length - 1 && itemType === 'blob';
        const path = parts.slice(0, index + 1).join('/');
        
        if (!pathMap[path]) {
          const node = {
            name: part,
            type: isFile ? 'blob' : 'tree',
            path: path,
            href: `https://gitcode.com/${currentRepo.owner}/${currentRepo.repo}/${isFile ? 'blob' : 'tree'}/${currentRepo.branch}/${path}`,
            children: isFile ? null : []
          };
          
          if (isFile) {
            node.size = item.size;
            node.id = item.id;
            node.sha = item.id || item.sha;
          }

          current.children.push(node);
          pathMap[path] = node;
          current = node;
        } else {
          current = pathMap[path];
        }
      });
    });

    console.log(`构建完成，根目录有 ${tree.children.length} 个项目`);
    return tree;
  }

  // 从 Contents API 构建树（已废弃，不再使用递归，改用懒加载）
  // 此函数保留仅用于兼容，实际不再调用
  async function buildTreeFromContentsAPI(contents, owner, repo, branch, currentPath = '', depth = 0) {
    console.warn('buildTreeFromContentsAPI 已被废弃，不应再调用');
    // 不再递归，只返回当前目录内容
    return { name: 'root', type: 'tree', children: contents.map(item => ({
      name: item.name,
      type: (item.type === 'file' || item.type === 'blob') ? 'blob' : 'tree',
      path: currentPath ? `${currentPath}/${item.name}` : item.name,
      children: (item.type === 'file' || item.type === 'blob') ? null : []
    })) };
    const tree = { name: 'root', type: 'tree', children: [] };
    
    // 限制递归深度，避免过深
    if (depth > 10) {
      console.warn('递归深度过深，停止获取');
      return tree;
    }
    
    // 确保 contents 是数组
    if (!Array.isArray(contents)) {
      console.warn('contents 不是数组:', contents);
      return tree;
    }
    
    // 处理当前目录的内容
    for (const item of contents) {
      // 检查 item 是否有效
      if (!item || !item.name) {
        console.warn('无效的 item:', item);
        continue;
      }
      
      const itemPath = currentPath ? `${currentPath}/${item.name}` : item.name;
      
      // 检查类型：file, dir, symlink 等
      const itemType = item.type || item.type_code || 'file';
      const isFile = itemType === 'file' || itemType === 'blob';
      const isDir = itemType === 'dir' || itemType === 'tree' || itemType === 'directory';
      
      // 如果既不是文件也不是目录，跳过
      if (!isFile && !isDir) {
        console.log(`跳过未知类型 ${itemType}: ${item.name}`);
        continue;
      }
      
      const node = {
        name: item.name,
        type: isFile ? 'blob' : 'tree',
        path: itemPath,
        href: `https://gitcode.com/${owner}/${repo}/${isFile ? 'blob' : 'tree'}/${branch}/${itemPath}`,
        children: isFile ? null : []
      };

      // 如果是目录，递归获取其内容
      if (isDir) {
        try {
          const apiToken = await getApiToken();
          const headers = {
            'Accept': 'application/json'
          };
          
          if (apiToken) {
            headers['Authorization'] = `Bearer ${apiToken}`;
            headers['PRIVATE-TOKEN'] = apiToken;
          }
          
          // 优先使用 gitcode.com 域名
          let dirUrl = `https://gitcode.com/api/v5/repos/${owner}/${repo}/contents/${encodeURIComponent(itemPath)}?ref=${branch}`;
          let dirResponse = null;
          
          try {
            dirResponse = await fetch(dirUrl, {
              method: 'GET',
              headers: headers,
              credentials: 'include'
            });
          } catch (fetchError) {
            console.log(`gitcode.com 请求失败，尝试 api.gitcode.com:`, fetchError);
          }
          
          // 如果失败，尝试 api.gitcode.com
          if (!dirResponse || !dirResponse.ok) {
            dirUrl = `https://api.gitcode.com/api/v5/repos/${owner}/${repo}/contents/${encodeURIComponent(itemPath)}?ref=${branch}`;
            try {
              dirResponse = await fetch(dirUrl, {
                method: 'GET',
                headers: headers
              });
            } catch (fetchError2) {
              console.log(`api.gitcode.com 请求也失败:`, fetchError2);
              dirResponse = null;
            }
          }
          
          if (dirResponse && dirResponse.ok) {
            const contentType = dirResponse.headers.get('content-type');
            if (contentType && contentType.includes('application/json')) {
              const dirText = await dirResponse.text();
              try {
                const dirData = JSON.parse(dirText);
                
                // 检查返回的是数组还是单个对象
                if (Array.isArray(dirData)) {
                  // 递归构建子目录
                  const subTree = await buildTreeFromContentsAPI(dirData, owner, repo, branch, itemPath, depth + 1);
                  node.children = subTree.children;
                  console.log(`目录 ${itemPath} 包含 ${subTree.children.length} 个文件/文件夹`);
                } else if (dirData && dirData.type === 'file') {
                  // 如果返回的是单个文件对象，说明路径错误（可能是文件而不是目录）
                  console.warn(`路径 ${itemPath} 是文件而不是目录，跳过递归`);
                  node.type = 'blob';
                  node.children = null;
                } else {
                  console.warn(`目录 ${itemPath} 返回了非数组数据:`, dirData);
                }
              } catch (parseError) {
                console.log(`解析目录 ${itemPath} 内容失败:`, parseError, '响应:', dirText.substring(0, 200));
              }
            } else {
              console.log(`目录 ${itemPath} 返回了非JSON内容，Content-Type:`, contentType);
            }
          } else {
            if (dirResponse) {
              console.log(`获取目录 ${itemPath} 失败，状态码:`, dirResponse.status);
              // 如果是404，可能是文件而不是目录
              if (dirResponse.status === 404) {
                console.warn(`路径 ${itemPath} 不存在，可能是文件路径错误`);
              }
            } else {
              console.log(`获取目录 ${itemPath} 失败，无法建立连接`);
            }
          }
        } catch (e) {
          console.log(`获取目录 ${itemPath} 内容失败:`, e);
          // 继续处理其他项目，不中断整个流程
        }
      }

      tree.children.push(node);
    }

    return tree;
  }

  // 统计树节点数量
  function countTreeNodes(tree) {
    if (!tree.children) return 0;
    let count = tree.children.length;
    tree.children.forEach(child => {
      if (child.children) {
        count += countTreeNodes(child);
      }
    });
    return count;
  }

  // 从DOM构建树
  function buildTreeFromDOM() {
    const tree = { name: 'root', type: 'tree', children: [] };
    const pathMap = {};
    const processedPaths = new Set();

    // 等待页面加载完成
    if (document.readyState === 'loading') {
      console.log('页面仍在加载，等待...');
      return new Promise((resolve) => {
        document.addEventListener('DOMContentLoaded', () => {
          resolve(buildTreeFromDOM());
        });
      });
    }

    // 方法1: 查找GitCode页面中的文件/目录链接
    // 支持多种选择器（GitCode/GitLab风格）
    const selectors = [
      'a[href*="/-/blob/"]',
      'a[href*="/-/tree/"]',
      'a[href*="/blob/"]',
      'a[href*="/tree/"]',
      '.tree-item a',
      '.file-row a',
      '[data-path] a',
      '.js-navigation-item a',
      '.file-list a',
      '.tree-list a',
      'table a[href*="blob"]',
      'table a[href*="tree"]',
      '.repository-content a',
      '[class*="file"] a',
      '[class*="tree"] a'
    ];

    let fileLinks = [];
    for (const selector of selectors) {
      try {
        const links = document.querySelectorAll(selector);
        if (links.length > 0) {
          fileLinks = Array.from(links);
          console.log(`找到 ${links.length} 个链接 (选择器: ${selector})`);
          break;
        }
      } catch (e) {
        console.log(`选择器 ${selector} 出错:`, e);
      }
    }

    // 如果没有找到，尝试更通用的方法
    if (fileLinks.length === 0) {
      console.log('尝试查找所有链接...');
      // 查找所有包含路径的链接
      const allLinks = document.querySelectorAll('a[href]');
      console.log(`页面中共有 ${allLinks.length} 个链接`);
      
      fileLinks = Array.from(allLinks).filter(link => {
        const href = link.getAttribute('href');
        if (!href) return false;
        
        // 检查是否是文件/目录链接
        return href.includes('/-/blob/') || 
               href.includes('/-/tree/') ||
               href.includes('/blob/') ||
               href.includes('/tree/') ||
               (href.startsWith('/') && href.split('/').length > 4); // 可能是文件路径
      });
      console.log(`通用方法找到 ${fileLinks.length} 个链接`);
      
      // 调试：输出前10个链接的href
      if (fileLinks.length === 0 && allLinks.length > 0) {
        console.log('调试信息 - 前10个链接的href:');
        Array.from(allLinks).slice(0, 10).forEach((link, idx) => {
          const href = link.getAttribute('href');
          const text = link.textContent.trim();
          console.log(`  ${idx + 1}. href: "${href}", text: "${text}"`);
        });
      }
      
      // 如果还是没找到，尝试查找文本内容
      if (fileLinks.length === 0) {
        console.log('尝试从文本内容查找文件...');
        fileLinks = Array.from(allLinks).filter(link => {
          const text = link.textContent.trim();
          const href = link.getAttribute('href');
          // 文件名通常包含点号或斜杠
          return text && (
            text.includes('.') || 
            text.includes('/') ||
            (href && href.match(/\/[^\/]+\/[^\/]+\/[^\/]+/))
          );
        });
        console.log(`从文本内容找到 ${fileLinks.length} 个可能的文件链接`);
      }
    }

    fileLinks.forEach(link => {
      const href = link.getAttribute('href');
      if (!href) return;

      // 匹配多种路径格式:
      // 1. /owner/repo/blob/branch/path 或 /owner/repo/tree/branch/path (GitCode格式)
      // 2. /blob/branch/path 或 /tree/branch/path (相对路径)
      let match = href.match(/\/(blob|tree)\/([^\/\?]+)\/(.+)/);
      if (!match) {
        // 尝试从完整URL中提取
        const urlMatch = href.match(/gitcode\.com\/[^\/]+\/[^\/]+\/(blob|tree)\/([^\/]+)\/(.+)/);
        if (urlMatch) {
          match = [null, urlMatch[1], urlMatch[2], urlMatch[3]];
        }
      }
      
      if (!match) {
        // 如果还是没匹配到，尝试从链接文本推断
        const text = link.textContent.trim();
        if (text && (text.includes('.') || text.includes('/'))) {
          // 可能是文件名或路径
          const path = text.startsWith('/') ? text.slice(1) : text;
          const parts = path.split('/').filter(p => p);
          if (parts.length > 0) {
            // 假设是文件（如果包含点号）或目录
            const isFile = parts[parts.length - 1].includes('.');
            let current = tree;
            parts.forEach((part, index) => {
              const fullPath = parts.slice(0, index + 1).join('/');
              if (!pathMap[fullPath]) {
                const node = {
                  name: part,
                  type: (index === parts.length - 1 && isFile) ? 'blob' : 'tree',
                  path: fullPath,
                  href: href,
                  children: (index === parts.length - 1 && isFile) ? null : []
                };
                current.children.push(node);
                pathMap[fullPath] = node;
                current = node;
              } else {
                current = pathMap[fullPath];
              }
            });
          }
        }
        return;
      }

      const [, type, branch, path] = match;
      
      // 跳过当前分支不匹配的链接（如果指定了分支）
      if (currentRepo.branch && branch && branch !== currentRepo.branch && branch !== 'master' && branch !== 'main') {
        return;
      }

      // 避免重复处理相同路径
      const pathKey = `${type}:${path}`;
      if (processedPaths.has(pathKey)) {
        return;
      }
      processedPaths.add(pathKey);

      const parts = path.split('/').filter(p => p); // 过滤空字符串
      if (parts.length === 0) return;

      let current = tree;

      parts.forEach((part, index) => {
        const isFile = index === parts.length - 1 && type === 'blob';
        const fullPath = parts.slice(0, index + 1).join('/');
        
        if (!pathMap[fullPath]) {
          const node = {
            name: part,
            type: isFile ? 'blob' : 'tree',
            path: fullPath,
            href: href.startsWith('http') ? href : `https://gitcode.com${href.startsWith('/') ? '' : '/'}${href}`,
            children: isFile ? null : []
          };

          current.children.push(node);
          pathMap[fullPath] = node;
          current = node;
        } else {
          current = pathMap[fullPath];
        }
      });
    });

    console.log(`DOM解析完成，找到 ${tree.children.length} 个顶级项目`);

    // 如果没有找到文件，尝试从页面结构解析
    if (tree.children.length === 0) {
      console.log('尝试从页面结构解析...');
      return buildTreeFromPageStructure();
    }

    return tree;
  }

  // 从页面结构构建树（备用方案）
  function buildTreeFromPageStructure() {
    const tree = { name: 'root', type: 'tree', children: [] };
    const pathMap = {};
    
    // 查找文件浏览器组件的多种选择器
    const selectors = [
      '[data-testid="file-browser"]',
      '.file-browser',
      '.tree-view',
      '.repository-content',
      '.file-list',
      '.js-navigation-container',
      '[role="tree"]',
      '.tree-list'
    ];

    let fileBrowser = null;
    for (const selector of selectors) {
      fileBrowser = document.querySelector(selector);
      if (fileBrowser) {
        console.log(`找到文件浏览器: ${selector}`);
        break;
      }
    }

    if (!fileBrowser) {
      console.log('未找到文件浏览器组件，尝试查找所有文件链接');
      // 最后尝试：查找页面中所有可能的文件链接
      const allLinks = document.querySelectorAll('a[href]');
      console.log(`页面中共有 ${allLinks.length} 个链接`);
      
      const repoLinks = Array.from(allLinks).filter(link => {
        const href = link.getAttribute('href');
        const text = link.textContent.trim();
        return href && (
          href.includes('/-/blob/') || 
          href.includes('/-/tree/') ||
          href.includes('/blob/') ||
          href.includes('/tree/') ||
          (text && text.includes('.')) // 可能是文件名
        );
      });

      if (repoLinks.length > 0) {
        console.log(`找到 ${repoLinks.length} 个可能的文件链接`);
        // 使用这些链接构建树
        repoLinks.forEach(link => {
          const href = link.getAttribute('href');
          const text = link.textContent.trim();
          if (!href || !text) return;

          let match = href.match(/\/-\/(blob|tree)\/([^\/]+)\/(.+)/);
          if (!match) {
            match = href.match(/\/(blob|tree)\/([^\/]+)\/(.+)/);
          }
          
          if (match) {
            const [, type, branch, path] = match;
            const parts = path.split('/').filter(p => p);
            if (parts.length === 0) return;

            let current = tree;
            parts.forEach((part, index) => {
              const isFile = index === parts.length - 1 && type === 'blob';
              const fullPath = parts.slice(0, index + 1).join('/');
              
              if (!pathMap[fullPath]) {
                const node = {
                  name: part,
                  type: isFile ? 'blob' : 'tree',
                  path: fullPath,
                  href: href,
                  children: isFile ? null : []
                };
                current.children.push(node);
                pathMap[fullPath] = node;
                current = node;
              } else {
                current = pathMap[fullPath];
              }
            });
          }
        });
        return tree;
      }
      
      // 调试：输出页面结构信息
      console.log('=== 页面结构调试信息 ===');
      console.log('当前URL:', window.location.href);
      console.log('页面标题:', document.title);
      console.log('主要容器:', document.querySelector('main, .main, .content, .repository-content, #content'));
      
      // 查找可能的文件列表容器
      const possibleContainers = [
        'table',
        'ul',
        '.file-list',
        '.tree-list',
        '[role="list"]',
        '.repository-content',
        'main',
        '.content'
      ];
      
      possibleContainers.forEach(selector => {
        const elements = document.querySelectorAll(selector);
        if (elements.length > 0) {
          console.log(`找到 ${elements.length} 个 "${selector}" 元素`);
        }
      });
      
      return tree;
    }

    // 递归解析DOM节点
    function parseNode(element, parent) {
      const items = element.querySelectorAll('li, [role="treeitem"], .tree-item, .file-row, tr');
      items.forEach(item => {
        const link = item.querySelector('a');
        if (!link) return;

        const text = link.textContent.trim();
        const href = link.getAttribute('href');
        if (!text || !href) return;

        const isDirectory = item.classList.contains('directory') || 
                          item.classList.contains('tree-item') ||
                          item.querySelector('.icon-folder, .fa-folder, [class*="folder"]') ||
                          (href && href.includes('/tree/')) ||
                          !text.includes('.'); // 没有扩展名可能是目录

        const match = href.match(/\/(blob|tree)\/([^\/]+)\/(.+)/);
        const path = match ? match[3] : text;

        const node = {
          name: text,
          type: isDirectory ? 'tree' : 'blob',
          path: path,
          href: href,
          children: isDirectory ? [] : null
        };

        parent.children.push(node);

        if (isDirectory) {
          const subList = item.querySelector('ul, [role="group"], .tree-children');
          if (subList) {
            parseNode(subList, node);
          }
        }
      });
    }

    parseNode(fileBrowser, tree);
    console.log(`页面结构解析完成，找到 ${tree.children.length} 个项目`);
    return tree;
  }

  // 渲染目录内容（树形结构，不隐藏已加载内容）
  function renderDirectoryContents(contents, path = '') {
    // 注意：这个函数现在主要用于初始化根目录
    // 子目录的渲染在 toggleNodeLazy 中完成，以保持树形结构
    
    const contentDiv = treeContainer.querySelector('.gitcode-tree-content');
    
    if (!contents || contents.length === 0) {
      contentDiv.innerHTML = '<div class="gitcode-tree-empty">目录为空</div>';
      return;
    }

    // 更新返回按钮显示状态（初始时隐藏，有展开目录时显示）
    const backBtn = treeContainer.querySelector('.gitcode-tree-back');
    if (backBtn) {
      backBtn.style.display = 'none';
    }

    // 渲染根目录文件列表（树形结构）
    let html = '';
    contents.forEach(item => {
      const itemType = item.type || item.type_code || 'file';
      const isFile = itemType === 'file' || itemType === 'blob';
      const isDir = itemType === 'dir' || itemType === 'tree' || itemType === 'directory';
      
      if (!isFile && !isDir) return;

      const itemPath = path ? `${path}/${item.name}` : item.name;
      const indent = 0; // 根目录缩进为0
      
      // 检查是否是当前文件
      const currentFilePath = getCurrentFilePath();
      const isCurrentFile = isFile && currentFilePath && itemPath === currentFilePath;
      
      html += `
        <div class="gitcode-tree-item ${isCurrentFile ? 'current-file' : ''}" data-path="${itemPath}" data-type="${isFile ? 'blob' : 'tree'}" data-loaded="false" style="padding-left: ${indent}px">
          <div class="gitcode-tree-item-content">
            ${isDir ? `
              <span class="gitcode-tree-toggle-icon">▶</span>
            ` : '<span class="gitcode-tree-spacer"></span>'}
            <span class="gitcode-tree-icon">
              ${isFile ? '<svg width="14" height="14" viewBox="0 0 16 16" fill="currentColor"><path d="M3.75 1.5a.25.25 0 0 0-.25.25v12.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25V6H9.75A1.75 1.75 0 0 1 8 4.25V1.5H3.75zm5.75.56v2.19c0 .138.112.25.25.25h2.19L9.5 2.06zM2 1.75C2 .784 2.784 0 3.75 0h5.086c.464 0 .909.184 1.237.513l3.414 3.414c.329.328.513.773.513 1.237v8.086A1.75 1.75 0 0 1 13.25 15h-8.5A1.75 1.75 0 0 1 3 13.25V1.75z"/></svg>' : '<svg width="14" height="14" viewBox="0 0 16 16" fill="currentColor"><path d="M1.75 1A1.75 1.75 0 0 0 0 2.75v10.5C0 14.216.784 15 1.75 15h12.5A1.75 1.75 0 0 0 16 13.25v-8.5A1.75 1.75 0 0 0 14.25 2.5H9.5a.25.25 0 0 1-.22-.137L8.688 1.5H1.75zm0 1.5h6.938a.25.25 0 0 1 .22.137l.593 1.363H14.25a.25.25 0 0 1 .25.25v8.5a.25.25 0 0 1-.25.25H1.75a.25.25 0 0 1-.25-.25v-10.5a.25.25 0 0 1 .25-.25z"/></svg>'}
            </span>
            <span class="gitcode-tree-name">${escapeHtml(item.name)}</span>
          </div>
          ${isDir ? `
            <div class="gitcode-tree-children" style="display: none;"></div>
          ` : ''}
        </div>
      `;
    });

    contentDiv.innerHTML = html || '<div class="gitcode-tree-empty">暂无文件</div>';

    // 绑定事件
    bindTreeEvents();
    
    // 高亮当前文件并滚动到可见位置（延迟执行，确保DOM已完全渲染）
    setTimeout(() => {
      highlightCurrentFile();
    }, 300);
  }

  // 高亮当前文件并自动展开路径
  async function highlightCurrentFile() {
    // 如果是手动收起操作，不执行自动定位
    if (isManualCollapse) {
      return;
    }
    
    const currentFilePath = getCurrentFilePath();
    if (!currentFilePath) return;
    
    // 移除之前的高亮
    if (treeContainer) {
      treeContainer.querySelectorAll('.gitcode-tree-item.current-file').forEach(item => {
        item.classList.remove('current-file');
      });
      
      // 找到当前文件并高亮（先尝试直接查找）
      let currentFileItem = null;
      const allItems = treeContainer.querySelectorAll('.gitcode-tree-item[data-type="blob"]');
      for (const item of allItems) {
        if (item.dataset.path === currentFilePath) {
          currentFileItem = item;
          break;
        }
      }
      
      // 如果文件不在当前DOM中，需要展开路径
      if (!currentFileItem) {
        await expandPathToFile(currentFilePath);
        // 重新查找
        const allItemsAfter = treeContainer.querySelectorAll('.gitcode-tree-item[data-type="blob"]');
        for (const item of allItemsAfter) {
          if (item.dataset.path === currentFilePath) {
            currentFileItem = item;
            break;
          }
        }
      }
      
      if (currentFileItem) {
        currentFileItem.classList.add('current-file');
        
        // 滚动到可见位置
        setTimeout(() => {
          currentFileItem.scrollIntoView({ behavior: 'smooth', block: 'center' });
        }, 300);
        
        // 确保所有父目录都展开，并正确设置状态（但跳过被手动收起的目录）
        let parent = currentFileItem.parentElement;
        while (parent && parent !== treeContainer) {
          if (parent.classList.contains('gitcode-tree-children')) {
            const parentItem = parent.closest('.gitcode-tree-item');
            if (parentItem) {
              const parentPath = parentItem.dataset.path;
              // 如果这个父目录被用户手动收起过，不自动展开
              if (!manuallyCollapsedPaths.has(parentPath)) {
                parent.style.display = 'block';
                const toggleIcon = parentItem.querySelector('.gitcode-tree-toggle-icon');
                if (toggleIcon) {
                  toggleIcon.classList.add('expanded');
                  toggleIcon.textContent = '▼';
                }
                // 标记为已加载，确保可以正常收起
                parentItem.dataset.loaded = 'true';
              }
            }
          }
          parent = parent.parentElement;
        }
      }
    }
  }

  // 展开路径到文件
  async function expandPathToFile(filePath) {
    // 如果是手动收起操作，不执行自动展开
    if (isManualCollapse) {
      return;
    }
    
    if (!filePath) return;
    
    const pathParts = filePath.split('/').filter(p => p);
    if (pathParts.length === 0) return;
    
    // 从根目录开始，逐级展开
    let currentPath = '';
    for (let i = 0; i < pathParts.length - 1; i++) { // 最后一个是文件名，不需要展开
      currentPath = currentPath ? `${currentPath}/${pathParts[i]}` : pathParts[i];
      
      // 如果这个路径被用户手动收起过，跳过自动展开
      if (manuallyCollapsedPaths.has(currentPath)) {
        continue;
      }
      
      // 查找对应的目录项（使用直接匹配，避免选择器问题）
      let dirItem = null;
      const allDirItems = treeContainer.querySelectorAll('.gitcode-tree-item[data-type="tree"]');
      for (const item of allDirItems) {
        if (item.dataset.path === currentPath) {
          dirItem = item;
          break;
        }
      }
      
      if (dirItem) {
        const childrenDiv = dirItem.querySelector('.gitcode-tree-children');
        const toggleIcon = dirItem.querySelector('.gitcode-tree-toggle-icon');
        const isLoaded = dirItem.dataset.loaded === 'true';
        
        // 如果未加载，先加载
        if (!isLoaded && childrenDiv) {
          await toggleNodeLazy(dirItem, currentPath);
        } else if (childrenDiv) {
          // 如果已加载，确保展开状态和UI状态正确
          const currentDisplay = childrenDiv.style.display || window.getComputedStyle(childrenDiv).display;
          if (currentDisplay === 'none') {
            // 如果未展开，展开它
            childrenDiv.style.display = 'block';
          }
          // 确保toggleIcon状态正确
          if (toggleIcon) {
            toggleIcon.classList.add('expanded');
            toggleIcon.textContent = '▼';
          }
          // 确保标记为已加载，这样才可以正常收起
          dirItem.dataset.loaded = 'true';
        }
        
        // 等待DOM更新
        await new Promise(resolve => setTimeout(resolve, 50));
      }
    }
  }

  // 更新返回按钮显示状态
  function updateBackButton() {
    const backBtn = treeContainer.querySelector('.gitcode-tree-back');
    if (backBtn) {
      const hasExpanded = treeContainer.querySelector('.gitcode-tree-children[style*="block"]');
      backBtn.style.display = hasExpanded ? 'inline-block' : 'none';
    }
  }

  // 返回上一级（树形模式下，收起当前展开的最深层目录）
  function goBack() {
    // 在树形模式下，返回上一级意味着收起当前展开的目录
    // 找到当前展开的最深层目录并收起
    const expandedItems = Array.from(treeContainer.querySelectorAll('.gitcode-tree-item[data-loaded="true"]'))
      .filter(item => {
        const children = item.querySelector('.gitcode-tree-children');
        return children && children.style.display !== 'none';
      });
    
    if (expandedItems.length > 0) {
      // 找到最深层（缩进最大）的展开项
      let maxIndent = -1;
      let deepestItem = null;
      
      expandedItems.forEach(item => {
        const indent = parseInt(item.style.paddingLeft) || 0;
        if (indent > maxIndent) {
          maxIndent = indent;
          deepestItem = item;
        }
      });
      
      if (deepestItem) {
        const toggleIcon = deepestItem.querySelector('.gitcode-tree-toggle-icon');
        const childrenDiv = deepestItem.querySelector('.gitcode-tree-children');
        if (toggleIcon && childrenDiv) {
          childrenDiv.style.display = 'none';
          toggleIcon.classList.remove('expanded');
          
          // 更新返回按钮显示状态
          updateBackButton();
        }
      }
    }
  }

  // 渲染树节点
  function renderTreeNode(node, filter = '', depth = 0) {
    if (!node.children || node.children.length === 0) {
      return '';
    }

    let html = '';
    const filteredChildren = filter 
      ? node.children.filter(child => 
          child.name.toLowerCase().includes(filter.toLowerCase()) ||
          (child.children && hasMatchingChild(child, filter))
        )
      : node.children;

    filteredChildren.forEach(child => {
      const isExpanded = child.expanded !== false && depth < 2; // 默认展开前2层
      const hasChildren = child.children && child.children.length > 0;
      const indent = depth * 20;
      
      html += `
        <div class="gitcode-tree-item" data-path="${child.path || ''}" data-type="${child.type}" data-href="${child.href || ''}" style="padding-left: ${indent}px">
          <div class="gitcode-tree-item-content">
            ${hasChildren ? `
              <span class="gitcode-tree-toggle-icon ${isExpanded ? 'expanded' : ''}">▶</span>
            ` : '<span class="gitcode-tree-spacer"></span>'}
            <span class="gitcode-tree-icon">
              ${child.type === 'blob' ? '📄' : '📁'}
            </span>
            <span class="gitcode-tree-name">${escapeHtml(child.name)}</span>
          </div>
          ${hasChildren && isExpanded ? `
            <div class="gitcode-tree-children">
              ${renderTreeNode(child, filter, depth + 1)}
            </div>
          ` : ''}
        </div>
      `;
    });

    return html;
  }

  // 检查是否有匹配的子节点
  function hasMatchingChild(node, filter) {
    if (!node.children) return false;
    return node.children.some(child => 
      child.name.toLowerCase().includes(filter.toLowerCase()) ||
      hasMatchingChild(child, filter)
    );
  }

  // 绑定树事件
  // 标记事件是否已绑定
  let treeEventsBound = false;

  function bindTreeEvents() {
    if (!treeContainer) return;
    
    // 如果已经绑定过事件，不再重复绑定
    if (treeEventsBound) return;
    treeEventsBound = true;

    // 使用事件委托，避免重复绑定
    treeContainer.addEventListener('click', (e) => {
      const toggleIcon = e.target.closest('.gitcode-tree-toggle-icon');
      const nameSpan = e.target.closest('.gitcode-tree-name');
      const item = e.target.closest('.gitcode-tree-item');
      
      if (!item) return;
      
      const type = item.dataset.type;
      const path = item.dataset.path;
      
      if (toggleIcon) {
        e.stopPropagation();
        e.preventDefault();
        toggleNodeLazy(item, path);
      } else if (nameSpan) {
        if (type === 'blob') {
          // 文件：打开文件
          e.stopPropagation();
          openFile(path);
        } else if (type === 'tree') {
          // 目录名称点击：展开/收起子目录（树形结构）
          e.stopPropagation();
          const currentToggleIcon = item.querySelector('.gitcode-tree-toggle-icon');
          if (currentToggleIcon) {
            toggleNodeLazy(item, path);
          }
        }
      }
    });
  }

  // 懒加载切换节点
  async function toggleNodeLazy(item, path) {
    const childrenDiv = item.querySelector('.gitcode-tree-children');
    const toggleIcon = item.querySelector('.gitcode-tree-toggle-icon');
    
    if (!childrenDiv || !toggleIcon) {
      console.warn('无法找到子目录容器或切换图标');
      return;
    }
    
    const isLoaded = item.dataset.loaded === 'true';
    
    // 判断是否展开：优先检查toggleIcon的状态，这是最可靠的
    const toggleIconText = toggleIcon.textContent.trim();
    const toggleIconHasExpandedClass = toggleIcon.classList.contains('expanded');
    const isToggleExpanded = toggleIconText === '▼' || toggleIconHasExpandedClass;
    
    // 同时检查display状态
    const inlineDisplay = childrenDiv.style.display;
    const computedDisplay = window.getComputedStyle(childrenDiv).display;
    // 如果inline style明确设置了display，使用inline style；否则使用computed style
    const actualDisplay = inlineDisplay !== '' ? inlineDisplay : computedDisplay;
    const isDisplayExpanded = actualDisplay !== 'none' && actualDisplay !== '';
    
    // 综合判断：toggleIcon状态优先，如果toggleIcon显示展开，就认为是展开的
    // 如果toggleIcon状态不明确，则使用display状态（但必须已加载）
    const isExpanded = isToggleExpanded || (isDisplayExpanded && isLoaded);
    
    // 调试信息（可以在控制台查看）
    console.log('toggleNodeLazy:', { path, isLoaded, toggleIconText, isToggleExpanded, actualDisplay, isDisplayExpanded, isExpanded });

    if (isExpanded) {
      // 收起 - 标记为手动收起，阻止自动定位
      isManualCollapse = true;
      // 记录手动收起的路径
      manuallyCollapsedPaths.add(path);
      childrenDiv.style.display = 'none';
      toggleIcon.classList.remove('expanded');
      toggleIcon.textContent = '▶';
      updateBackButton();
      // 延迟重置标志，确保不会触发自动定位
      setTimeout(() => {
        isManualCollapse = false;
      }, 500);
      return; // 收起时直接返回，不执行后续逻辑
    } else {
      // 展开时重置标志，并从手动收起列表中移除（用户主动展开）
      isManualCollapse = false;
      manuallyCollapsedPaths.delete(path);
      // 展开
      if (!isLoaded) {
        // 首次展开，需要加载子目录
        toggleIcon.textContent = '⋯';
        childrenDiv.innerHTML = '<div class="gitcode-tree-loading" style="padding: 8px 16px;">加载中...</div>';
        childrenDiv.style.display = 'block';
        
        try {
          const contents = await fetchDirectoryContents(path);
          if (contents && contents.length > 0) {
            // 渲染子目录内容
            let html = '';
            contents.forEach(childItem => {
              const childType = childItem.type || childItem.type_code || 'file';
              const isFile = childType === 'file' || childType === 'blob';
              const isDir = childType === 'dir' || childType === 'tree' || childType === 'directory';
              
              if (!isFile && !isDir) return;

              const childPath = `${path}/${childItem.name}`;
              // 计算缩进：根据路径深度（父目录的缩进 + 20）
              const parentIndent = parseInt(item.style.paddingLeft) || 0;
              const indent = parentIndent + 20;
              
              // 检查是否是当前文件
              const currentFilePath = getCurrentFilePath();
              const isCurrentFile = isFile && currentFilePath && childPath === currentFilePath;
              
              html += `
                <div class="gitcode-tree-item ${isCurrentFile ? 'current-file' : ''}" data-path="${childPath}" data-type="${isFile ? 'blob' : 'tree'}" data-loaded="false" style="padding-left: ${indent}px">
                  <div class="gitcode-tree-item-content">
                    ${isDir ? `
                      <span class="gitcode-tree-toggle-icon">▶</span>
                    ` : '<span class="gitcode-tree-spacer"></span>'}
                    <span class="gitcode-tree-icon">
                      ${isFile ? '<svg width="14" height="14" viewBox="0 0 16 16" fill="currentColor"><path d="M3.75 1.5a.25.25 0 0 0-.25.25v12.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25V6H9.75A1.75 1.75 0 0 1 8 4.25V1.5H3.75zm5.75.56v2.19c0 .138.112.25.25.25h2.19L9.5 2.06zM2 1.75C2 .784 2.784 0 3.75 0h5.086c.464 0 .909.184 1.237.513l3.414 3.414c.329.328.513.773.513 1.237v8.086A1.75 1.75 0 0 1 13.25 15h-8.5A1.75 1.75 0 0 1 3 13.25V1.75z"/></svg>' : '<svg width="14" height="14" viewBox="0 0 16 16" fill="currentColor"><path d="M1.75 1A1.75 1.75 0 0 0 0 2.75v10.5C0 14.216.784 15 1.75 15h12.5A1.75 1.75 0 0 0 16 13.25v-8.5A1.75 1.75 0 0 0 14.25 2.5H9.5a.25.25 0 0 1-.22-.137L8.688 1.5H1.75zm0 1.5h6.938a.25.25 0 0 1 .22.137l.593 1.363H14.25a.25.25 0 0 1 .25.25v8.5a.25.25 0 0 1-.25.25H1.75a.25.25 0 0 1-.25-.25v-10.5a.25.25 0 0 1 .25-.25z"/></svg>'}
                    </span>
                    <span class="gitcode-tree-name">${escapeHtml(childItem.name)}</span>
                  </div>
                  ${isDir ? `
                    <div class="gitcode-tree-children" style="display: none;"></div>
                  ` : ''}
                </div>
              `;
            });
            
            childrenDiv.innerHTML = html;
            // 先设置display为block，确保状态一致
            childrenDiv.style.display = 'block';
            // 然后设置加载状态和toggleIcon状态
            item.dataset.loaded = 'true';
            toggleIcon.classList.add('expanded');
            toggleIcon.textContent = '▼';
            
            // 更新返回按钮显示状态
            updateBackButton();
            
            // 绑定新添加的子节点事件
            bindTreeEvents();
            
            // 高亮当前文件（延迟执行，确保DOM已更新）
            // 但只在非手动收起时执行，避免自动展开被手动收起的目录
            // 注意：只有在用户主动展开目录时才高亮，不要在加载子目录时自动高亮
            // 这里不调用 highlightCurrentFile，避免在展开其他目录时自动展开当前文件的目录
          } else {
            childrenDiv.innerHTML = '<div class="gitcode-tree-empty" style="padding: 8px 16px;">目录为空</div>';
            item.dataset.loaded = 'true';
            toggleIcon.classList.add('expanded');
            toggleIcon.textContent = '▼';
          }
        } catch (error) {
          console.error('加载子目录失败:', error);
          childrenDiv.innerHTML = '<div class="gitcode-tree-error" style="padding: 8px 16px;">加载失败</div>';
          toggleIcon.textContent = '▶';
        }
      } else {
        // 已加载，直接展开
        isManualCollapse = false; // 展开时重置标志
        // 确保所有状态都正确设置
        childrenDiv.style.display = 'block';
        item.dataset.loaded = 'true'; // 确保data-loaded状态正确
        toggleIcon.classList.add('expanded');
        toggleIcon.textContent = '▼';
        updateBackButton();
        
        // 已加载目录的展开操作：不自动高亮当前文件，避免自动展开被手动收起的目录
        // 用户需要手动点击文件或刷新页面才会高亮
      }
      
      // 收起时也更新返回按钮
      if (isExpanded) {
        updateBackButton();
      }
    }
  }

  // 进入目录
  async function enterDirectory(path) {
    // 将当前路径加入栈
    if (currentPath) {
      pathStack.push(currentPath);
    }
    currentPath = path;
    
    // 加载新目录
    await loadFileTree(path);
  }

  // 切换节点展开/收起
  function toggleNode(item) {
    const children = item.querySelector('.gitcode-tree-children');
    const toggleIcon = item.querySelector('.gitcode-tree-toggle-icon');
    
    if (children) {
      const isExpanded = children.style.display !== 'none';
      children.style.display = isExpanded ? 'none' : 'block';
      toggleIcon.classList.toggle('expanded', !isExpanded);
    }
  }

  // 展开/收起所有节点（懒加载模式下，只展开已加载的）
  function toggleAllNodes(expand) {
    if (!treeContainer) return;
    
    treeContainer.querySelectorAll('.gitcode-tree-children').forEach(children => {
      if (children.innerHTML.trim() !== '') {
        children.style.display = expand ? 'block' : 'none';
      }
    });
    
    treeContainer.querySelectorAll('.gitcode-tree-toggle-icon').forEach(icon => {
      if (icon.textContent !== '⋯') {
        icon.classList.toggle('expanded', expand);
      }
    });
  }

  // 过滤树
  function filterTree(filter) {
    if (!fileTree) return;
    renderTree(fileTree, filter);
  }

  // 打开文件
  function openFile(path) {
    if (!path) return;
    
    const { owner, repo, branch } = currentRepo;
    
    // 如果path已经是完整URL，直接使用
    if (path.startsWith('http')) {
      window.open(path, '_blank');
      return;
    }
    
    // GitCode URL格式: https://gitcode.com/owner/repo/blob/branch/path
    const url = `https://gitcode.com/${owner}/${repo}/blob/${branch}/${path}`;
    window.open(url, '_blank');
  }

  // 切换显示/隐藏
  function toggleTreeViewer() {
    isVisible = !isVisible;
    chrome.storage.local.set({ [CONFIG.storageKey]: isVisible });
    
    if (isVisible) {
      createTreeViewer();
    } else {
      removeTreeViewer();
    }
  }

  // 切换Token设置面板
  function toggleTokenPanel() {
    const tokenPanel = treeContainer.querySelector('#tokenPanel');
    if (tokenPanel) {
      const isVisible = tokenPanel.style.display !== 'none';
      tokenPanel.style.display = isVisible ? 'none' : 'block';
    }
  }

  // 保存Token（内联）
  function saveTokenInline() {
    const tokenInput = treeContainer.querySelector('#tokenInputInline');
    const saveBtn = treeContainer.querySelector('#saveTokenInline');
    
    if (!tokenInput || !saveBtn) return;
    
    const token = tokenInput.value.trim();
    if (token) {
      chrome.storage.local.set({ [CONFIG.tokenKey]: token }, () => {
        tokenInput.value = token.replace(/./g, '*');
        tokenInput.dataset.hasValue = 'true';
        saveBtn.textContent = '已保存 ✓';
        saveBtn.style.background = '#28a745';
        
        setTimeout(() => {
          saveBtn.textContent = '保存Token';
          saveBtn.style.background = '#0366d6';
          toggleTokenPanel();
          // 刷新文件树
          loadFileTree(currentPath || '');
        }, 1500);
      });
    } else {
      saveBtn.textContent = '请输入Token';
      saveBtn.style.background = '#cb2431';
      setTimeout(() => {
        saveBtn.textContent = '保存Token';
        saveBtn.style.background = '#0366d6';
      }, 2000);
    }
  }

  // 移除代码树查看器
  function removeTreeViewer() {
    if (treeContainer) {
      treeContainer.remove();
      treeContainer = null;
    }
  }

  // 使容器可调整大小
  function makeResizable() {
    if (!treeContainer) return;
    
    const resizeHandle = document.createElement('div');
    resizeHandle.className = 'gitcode-tree-resize-handle';
    treeContainer.appendChild(resizeHandle);

    let isResizing = false;
    resizeHandle.addEventListener('mousedown', (e) => {
      isResizing = true;
      document.addEventListener('mousemove', handleResize);
      document.addEventListener('mouseup', stopResize);
      e.preventDefault();
    });

    function handleResize(e) {
      if (!isResizing) return;
      const newWidth = window.innerWidth - e.clientX;
      if (newWidth > 200 && newWidth < 600) {
        treeContainer.style.width = newWidth + 'px';
        CONFIG.treeWidth = newWidth;
      }
    }

    function stopResize() {
      isResizing = false;
      document.removeEventListener('mousemove', handleResize);
      document.removeEventListener('mouseup', stopResize);
    }
  }

  // HTML转义
  function escapeHtml(text) {
    const div = document.createElement('div');
    div.textContent = text;
    return div.innerHTML;
  }

  // 页面加载完成后初始化
  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', init);
  } else {
    init();
  }

  // 监听URL变化（SPA应用）
  let lastUrl = location.href;
  new MutationObserver(() => {
    const url = location.href;
    if (url !== lastUrl) {
      lastUrl = url;
      if (isRepoPage() && isVisible) {
        removeTreeViewer();
        setTimeout(createTreeViewer, 500);
      }
    }
  }).observe(document, { subtree: true, childList: true });

})();

